package Controllers;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;

import Entities.ForgotPasswordEntity;
import Entities.LoginEntity;
import Entities.RegisterEntity;
import Entities.WindowClose;
import GUI.CustomerRelationsGUI;
import GUI.ForgotPasswordGUI;
import GUI.LoginGUI;
import GUI.MainWindowGUI;
import GUI.MarketingManagerGUI;
import GUI.MarketingEmployeeGUI;
import GUI.RegisterGUI;
import GUI.SalesManGUI;
import Server.RsWraper;
import Server.Tuple;

/**
 * LoginController class implements Validate interface.
 * This class controls user login event.
 * @author Ofek-az
 *
 */

public class LoginController implements Validate,Observer {
	/**
	 * This is login boundary.
	 */
	private LoginGUI loginGui;
	/**
	 * This is login entity.
	 */
	private LoginEntity loginEnt;
	
	/** The tuples. */
	private ArrayList<Tuple> tuples;
	
	/** The main window. */
	public static MainWindowGUI mainWindow;
	
	/** The operation. */
	private int operation=0;
	
	private ArrayList<LoginEntity> users;
	public LoginController(LoginEntity loginEnt)
	{
		this.loginEnt=loginEnt;
	}
	public LoginController(ArrayList<LoginEntity> users)
	{
		this.users=users;
	}
	/**
	 * This is the class constructor.
	 *
	 * @param loginGui This is login boundary.
	 * @param loginEnt This is login entity.
	 */
	public LoginController(LoginGUI loginGui,LoginEntity loginEnt)
	{
		this.loginGui=loginGui;
		this.loginEnt=loginEnt;
		ClientController.setObserver(this);
		this.loginGui.addWindowListener(new WindowClose());
		this.loginGui.addLoginActionListener(new LoginListener());
		this.loginGui.addRegisterActionListener(new RegisterListener());
		this.loginGui.addForgotPasswordActionListener(new ForgotPasswordListener());
		this.loginGui.setVisible(true);
	}
	
	/* (non-Javadoc)
	 * @see Controllers.Validate#validateInput()
	 */
	public boolean validateInput()
	{
		String id=loginEnt.getUid(),pass=loginEnt.getPassword();
		if(id.equals("")||pass.equals(""))
		{
		//	loginGui.displayWarningMessage("Please fill all the missing fields.");
			return false;
		}
		else
		{
			try
			{
			Integer.parseInt(id);
			return true;
			}
			catch (NumberFormatException e)
			{
			//	loginGui.displayWarningMessage("Error:illeagel characters in id field.");
				return false;
			}
		}
		
	}
	
	/**
	* LoginListener class implements ActionListener interface.
	* this class controls the login button.
	 * @author Ofek-az
	 *
	 */
	class LoginListener implements ActionListener
	{
		
		/* (non-Javadoc)
		 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
		 */
		@Override
		public void actionPerformed(ActionEvent e) {
		login();
		}
	}
	public void login()
	{
		insertUserDetails(loginGui.getIdField().getText(),loginGui.getPasswordField().getText());
		if(validateInput())
		{
			String id=loginEnt.getUid();
			String pass=loginEnt.getPassword();
			String query = "SELECT users.uid,users.loginStatus FROM users WHERE users.uid= '"+id+"' AND users.password= '"+pass+"'" ;	//user info query.
			try {
				ClientController.observableClient.sendToServer(query);
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			
		}
	}
	public void insertUserDetails(String id,String password)
	{
		loginEnt.setUid(id);
		loginEnt.setPassword(password);
	}
	/**
	* RegisterListener class implements ActionListener interface.
	* this class controls the register button.
	 * @author Ofek-az
	 *
	 */
	class RegisterListener implements ActionListener
	{

		/* (non-Javadoc)
		 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
		 */
		@Override
		public void actionPerformed(ActionEvent e) {
			new RegisterController(new RegisterGUI(), new RegisterEntity()).setPrev(LoginController.this);
			loginGui.dispose();
			
		}
		
	}
	
	/**
	* ForgotPasswordListener class implements ActionListener interface.
	* this class controls the forgotPassword button.
	 * @author Ofek-az
	 *
	 */
	class ForgotPasswordListener implements ActionListener
	{

		/* (non-Javadoc)
		 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
		 */
		@Override
		public void actionPerformed(ActionEvent e) {
			new ForgotPasswordController(new ForgotPasswordGUI(), new ForgotPasswordEntity()).setPrev(LoginController.this);
			loginGui.dispose();
		}
		
	}

	/* (non-Javadoc)
	 * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
	 */
	@Override
	public void update(Observable o, Object arg) {
		
		String query;
		
		String msg = (String) arg.toString();
		if(msg.startsWith("#OC"))
				System.out.println(msg);
		else
		if(msg.equals("empty query")||msg.equals("error"))
			loginGui.displayWarningMessage("User id or password is incorrect");
		else
		if(msg.equals("#Server:Action succeded"))
		{
			query = "SELECT employees.position FROM employees WHERE employees.eid= '"+loginEnt.getUid()+"'";	//get the user position(access level) query.
			try {
				ClientController.observableClient.sendToServer(query);
				operation=1;
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		else
		{
			if(operation==0&&!msg.equals("empty query"))//update login status
			{
			tuples=((RsWraper) arg).getRows();
		//get user information
			try {
					
					loginEnt.setLoginStatus(tuples.get(0).get("LOGINSTATUS"));
					if(Integer.parseInt(loginEnt.getLoginStatus())==0) //check if user is not logged in yet.
					{
					query="UPDATE users SET `loginStatus`='1' WHERE `uid`='"+loginEnt.getUid()+"'";			//updating login status query.
					ClientController.observableClient.sendToServer(query);
					
				
					}
					else
						loginGui.displayWarningMessage("User is already logged in");
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			
			}
			else
			if(operation==1)//get access level
			{
					tuples=((RsWraper) arg).getRows();
					loginEnt.setPosition(tuples.get(0).get("POSITION"));
					
					//Open appropriate window.
					switch (loginEnt.getPosition()) {
					case "ME":	//Open Marketing employee window.
						MarketingEmployeeGUI mEmployeeGUI=new MarketingEmployeeGUI();
						new MarketingEmployeeController(mEmployeeGUI,0);
						mainWindow=new MainWindowGUI(mEmployeeGUI,loginEnt);
						mainWindow.setTitle("Marketing employee");
						break;
					case "MM":	//Open Marketing manager window.
						MarketingManagerGUI mManagerGUI=new MarketingManagerGUI();
						new MarketingManagerController(mManagerGUI);
						mainWindow=new MainWindowGUI(mManagerGUI,loginEnt);		
						mainWindow.setTitle("Marketing manager");
						break;
					case "CRE":	//Open Customer relations employee window.	
						CustomerRelationsGUI cRelationsGUI=new CustomerRelationsGUI();
						new CustomerRelationsController(cRelationsGUI);
						mainWindow=new MainWindowGUI(cRelationsGUI,loginEnt);
						mainWindow.setTitle("Customer relations employee");
						break;
					case "SM":	//Open Sales man window.
						SalesManGUI smGUI=new SalesManGUI();
						new SalesManController(smGUI, loginEnt);
						mainWindow=new MainWindowGUI(smGUI,loginEnt);
						mainWindow.setTitle("Sales man");
						break;
					}
					operation=0;
					loginGui.dispose();
					
			}
			}
			
		}
	
	/**
	 * Gets the login entity.
	 *
	 * @return the login entity
	 */
	public LoginEntity getLoginEnt() {
		return loginEnt;
	}
	
	/**
	 * Sets the login entity.
	 *
	 * @param loginEnt the new login entity
	 */
	public void setLoginEnt(LoginEntity loginEnt) {
		this.loginEnt = loginEnt;
	}
	
	/**
	 * Gets the login gui.
	 *
	 * @return the login gui
	 */
	public LoginGUI getLoginGui() {
		return loginGui;
	}
	
	/**
	 * Sets the login gui.
	 *
	 * @param loginGui the new login gui
	 */
	public void setLoginGui(LoginGUI loginGui) {
		this.loginGui = loginGui;
	}
	public ArrayList<LoginEntity> getUsers() {
		return users;
	}
	public void setUsers(ArrayList<LoginEntity> users) {
		this.users = users;
	}
	
	
	//functions for testing
	public int getIndexOfUser(String uid)
	{
		for(int i=0;i<users.size();i++)
			if(users.get(i).getUid().equals(uid))
				return i;
		return -1;
	}
	public boolean isUserExists(String uid)
	{
		if(getIndexOfUser(uid)!= -1)
			return true;
		return false;
	}
	public boolean checkPassword(String uid,String password)
	{
		int i=getIndexOfUser(uid);
		if(i!= -1)
		{
			if(users.get(i).getPassword().equals(password))
				return true;
		}
			return false;
	}
	public LoginEntity getUserInfo(String uid)
	{
		int i=getIndexOfUser(uid);
		if(i!=-1)
		return users.get(i);
		return null;
	}
	public boolean isUserLoggedIn(String uid)
	{
		int i=getIndexOfUser(uid);
		if(i!=-1)
		if(users.get(i).getLoginStatus().equals("1"))
		return true;
		return false;
	}
	public boolean changeLoginStatus(String uid)
	{
		int i=getIndexOfUser(uid);
		if(i!=-1)
		{
			if(!isUserLoggedIn(uid))
			{
				users.get(i).setLoginStatus("1");
				return true;
			}
		}
		return false;
		
	}
}
